import os
import gobject
import gtk
import gtk.glade
from BuildWizException import BuildWizException
from DlgDeployPen import DlgDeployPen
from AddVariableWin import AddVariableWin
from DlgFileSelection import DlgFileSelection
from ScriptWindow import ScriptWindow
from DlgDirectorySelection import DlgDirectorySelection
from DlgImportVariables import DlgImportVariables
from Variable import Variable

class ConfigWindow:
    def __init__( self, gladeFile, wizard, mainwin):
        if not os.path.isfile( gladeFile):
            raise BuildWizException( "ConfigWindow: libglade could not open - [%s]" % gladeFile)
        self.gladeFile = gladeFile
        self.__wiz = wizard
        self.__mainWin = mainwin
        self.__dataHasChanged = False
        self.__platfVars = {}
        self.__isInitialShowVariables = False
        self.__platfChangedConfigs = ""
        self.__scriptWinFile = self.__wiz.getPreferences().getGUIFile( "scriptwindow")
        self.xml = gtk.glade.XML( self.gladeFile)
        if self.xml:
            self.win = self.xml.get_widget( "ConfigWindow")
            self.__setVarView()
            self.win.connect( "destroy", self.destroy)
            self.handlers = { "on_btnPenSettings_clicked":self.onBtnPenSettings
                , "on_btnLocalSettings_clicked":          self.onBtnLocalSettings
                , "on_btnRemoteSettings_clicked":         self.onBtnRemoteSettings
                , "on_btnBoardSettings_clicked":          self.onBtnBoardSettings
                , "on_btnApply_clicked":                  self.__onBtnApply
                , "on_btnOk_clicked":                     self.__onBtnOk
                , "on_btnCancel_clicked":                 self.__onBtnCancel 
                , "on_btnAdd_clicked":                    self.__onAddVar
                , "on_btnDel_clicked":                    self.__onDelVar
                , "on_btnEditScriptBefore_clicked":       self.__onEditScriptBefore
                , "on_btnEditScriptAfter_clicked":        self.__onEditScriptAfter
                , "on_checkbtnRunMakeInst_toggled":       self.__onCheckRunMakeInstall
                , "on_spinbtnMakeJobs_changed":           self.__onSetNumMakeJobs
                , "on_checkbtnRunScriptAfter_toggled":    self.__onCheckRunScriptAfter
                , "on_checkbtnRunScriptBefore_toggled":   self.__onCheckRunScriptBefore
                , "on_entryScriptBefore_changed":         self.__onEntryScriptBeforeChanged
                , "on_textviewDescr_insert_at_cursor":    self.__onDescriptionChanged
                , "on_entryProjDir_changed":              self.__onProjDirChanged
                , "on_btnBrowseProjDir_clicked":          self.__onBtnProjDir
                , "on_entryBuildDir_changed":             self.__onBuildDirChanged
                , "on_btnBrowseBuildDir_clicked":         self.__onBtnBuildDir
                , "on_entryCMakeListsDir_changed":        self.__onCMakeListsDirChanged
                , "on_btnBrowseCmakelists_clicked":       self.__onBtnCMakeListsDir
                , "on_checkbtnSubvVerify_toggled":        self.__onCheckVerifySubversion
                , "on_btnImportCMakeVars_clicked":        self.__onImportClicked
                }
            self.xml.signal_autoconnect( self.handlers)
            self.__btnAdd = self.xml.get_widget( "btnAdd")
            self.__btnAdd.set_sensitive( False)
            self.__btnDel = self.xml.get_widget( "btnDel")
            self.__btnDel.set_sensitive( False)
            self.__comboPlatf = self.xml.get_widget( "cmbboxPlatform")
            self.__comboPlatf.child.set_property( 'editable', False)
            self.__comboPlatf.child.connect( 'changed', self.__onCmbboxPlatform)
            self.__liststore = gtk.ListStore( str)
            self.__comboPlatf.set_model( self.__liststore)
            self.__btnApply = self.xml.get_widget( "btnApply")
            self.__btnApply.set_sensitive( False)
            self.__insertPlatformItems()
            self.__spinbtnMakeJobs = self.xml.get_widget( "spinbtnMakeJobs")
            self.__spinbtnMakeJobs.set_sensitive( False)
            self.__checkbtnRunMakeInst = self.xml.get_widget( "checkbtnRunMakeInst")
            self.__checkbtnRunMakeInst.set_sensitive( False)
            self.__btnEditScriptBefore = self.xml.get_widget( "btnEditScriptBefore")
            self.__btnEditScriptBefore.set_sensitive( False)
            self.__btnEditScriptAfter = self.xml.get_widget( "btnEditScriptAfter")
            self.__btnEditScriptAfter.set_sensitive( False)
            self.__entryScriptBefore = self.xml.get_widget( "entryScriptBefore")
            self.__entryScriptBefore.set_sensitive( False)
            self.__entryScriptAfter = self.xml.get_widget( "entryScriptAfter")
            self.__entryScriptAfter.set_sensitive( False)
            self.__checkbtnRunScriptBefore = self.xml.get_widget( "checkbtnRunScriptBefore")
            self.__checkbtnRunScriptBefore.set_sensitive( False)
            self.__checkbtnRunScriptAfter = self.xml.get_widget( "checkbtnRunScriptAfter")
            self.__checkbtnRunScriptAfter.set_sensitive( False)
            self.__textviewDescr = self.xml.get_widget( "textviewDescr")
            self.__textviewDescr.set_sensitive( False)
            self.__entryProjDir = self.xml.get_widget( "entryProjDir")
            self.__entryProjDir.set_sensitive( False)
            self.__entryBuildDir = self.xml.get_widget( "entryBuildDir")
            self.__entryBuildDir.set_sensitive( False)
            self.__entryCMakeListsDir = self.xml.get_widget( "entryCMakeListsDir")
            self.__entryCMakeListsDir.set_sensitive( False)
            self.__btnBrowseProjDir = self.xml.get_widget( "btnBrowseProjDir")
            self.__btnBrowseProjDir.set_sensitive( False)
            self.__btnBrowseBuildDir = self.xml.get_widget( "btnBrowseBuildDir")
            self.__btnBrowseBuildDir.set_sensitive( False)
            self.__btnBrowseCmakelists = self.xml.get_widget( "btnBrowseCmakelists")
            self.__btnBrowseCmakelists.set_sensitive( False)
            self.__checkbtnSubvVerify = self.xml.get_widget( "checkbtnSubvVerify")
            self.__checkbtnSubvVerify.set_sensitive( False)
            self.__entrySubvRevisionNumb = self.xml.get_widget( "entrySubvRevisionNumb")
            self.__entrySubvURL = self.xml.get_widget( "entrySubvURL")
            self.__notebook = self.xml.get_widget( "notebookConfig")
            self.__notebook.set_sensitive( False)
            
            # Deploy
            self.__checkbtnDeployPen = self.xml.get_widget( "chkbtnPen")
            self.__btnPenSettings = self.xml.get_widget( "btnPenSettings")
            #self.__btnPenSettings.set_sensitive( False)

    def show( self):
        self.win.show_all()

    def isActive( self):
        return self.win.is_active()

    def __insertPlatformItems( self):
        for item in self.__wiz.getPlatforms().values():
            strItem = item.getID()
            self.__liststore.append( [strItem])
        self.__comboPlatf.set_text_column( 0)

        # This will produce a undesired effect setting the first entry and emiting a signal 
        #self.__comboPlatf.set_active( 0)  

    def __setVarView( self):
        self.treeStore = gtk.TreeStore( gobject.TYPE_STRING
                                      , gobject.TYPE_STRING
                                      , gobject.TYPE_STRING)
        self.treeStore.connect( 'row_changed', self.__onColumnChanged)
        self.win.treeview = self.xml.get_widget( "treeViewVariables")
        if self.win.treeview:
            self.win.treeview.set_model( self.treeStore) 

            self.rendererPlatform = gtk.CellRendererText()
            self.rendererPlatform.set_property( 'editable', True)
            self.rendererPlatform.connect( 'edited', self.__onCellEdited, self.treeStore, 0)
            self.columnVar = gtk.TreeViewColumn( "VARIABLE"
                                               , self.rendererPlatform
                                               , text=0)
            self.__rendererType = gtk.CellRendererText()
            self.__rendererType.set_property( 'editable', True)
            self.__rendererType.connect( 'edited', self.__onCellEdited, self.treeStore, 1)
            self.columnType = gtk.TreeViewColumn( "TYPE"
                                                , self.__rendererType
                                                , text=1)
            self.__rendererValue = gtk.CellRendererText()
            self.__rendererValue.set_property( 'editable', True)
            self.__rendererValue.connect( 'edited', self.__onCellEdited, self.treeStore, 2)
            self.columnValue = gtk.TreeViewColumn( "VALUE"
                                                 , self.__rendererValue
                                                 , text=2)
            self.win.treeview.append_column( self.columnVar)
            self.win.treeview.append_column( self.columnType)
            self.win.treeview.append_column( self.columnValue)
            self.win.treeview.set_search_column( 0)
            self.columnVar.set_sort_column_id( 0)

    def __onCellEdited( self, cell, path, newText, model, column):
        model[ path][ column] = newText

    def __shouldSaveConfigs( self):
        if len( self.__platfChangedConfigs) > 0:
            msg = "Platform [" + self.__platfChangedConfigs + "] configuration has changed but saved yet.\nDo you want to save it before continue?"
            dlg = gtk.MessageDialog( None, 0, gtk.MESSAGE_WARNING
                                   , gtk.BUTTONS_YES_NO
                                   , msg)
            response = dlg.run()
            dlg.destroy()
            if response == gtk.RESPONSE_YES:
                return True
            else:
                return False
        return False

    def __onCmbboxPlatform( self, entry):
        try:
            if self.__shouldSaveConfigs():
                self.__onBtnApply( None)
                
            name = entry.get_text()
            self.__wiz.reloadPlatform( name)
            self.__notebook.set_sensitive( True)
            self.treeStore.clear()
            self.__isInitialShowVariables = True
            self.__showValues( self.__wiz.getPlatformConfigVariables( name))
            self.__btnBrowseProjDir.set_sensitive( True)
            self.__btnBrowseBuildDir.set_sensitive( True)
            self.__btnBrowseCmakelists.set_sensitive( True)
            self.__btnAdd.set_sensitive( True)
            self.__btnDel.set_sensitive( True)
            self.__btnApply.set_sensitive( False)
            self.__spinbtnMakeJobs.set_sensitive( True)
            self.__spinbtnMakeJobs.set_value( float( self.__wiz.getNumMakeJobs( name)))
            self.__checkbtnRunMakeInst.set_active( self.__wiz.getRunMakeInstall( name))
            self.__checkbtnRunMakeInst.set_sensitive( True)
            self.__entryScriptBefore.set_text( self.__wiz.getScriptBefore( name))
            self.__entryScriptAfter.set_text( self.__wiz.getScriptAfter( name))
            self.__checkbtnRunScriptBefore.set_sensitive( True)
            self.__checkbtnRunScriptBefore.set_active( self.__wiz.getRunScriptBefore( name))
            self.__checkbtnRunScriptAfter.set_sensitive( True)
            self.__checkbtnRunScriptAfter.set_active( self.__wiz.getRunScriptAfter( name))
            self.__setScriptAreaSensibility( self.__entryScriptBefore
                                           , self.__btnEditScriptBefore
                                           , self.__checkbtnRunScriptBefore.get_active())
            self.__setScriptAreaSensibility( self.__entryScriptAfter
                                           , self.__btnEditScriptAfter
                                           , self.__checkbtnRunScriptAfter.get_active())
            if self.__wiz.isPlatformWorkingCopy( name):
                self.__checkbtnSubvVerify.set_sensitive( True)
                self.__entrySubvRevisionNumb.set_sensitive( True)
                self.__entrySubvRevisionNumb.set_text( str( self.__wiz.getPlatformSubversionRevision( name)))
                self.__entrySubvURL.set_sensitive( True)
                self.__entrySubvURL.set_text( self.__wiz.getPlatformSubversionURL( name))
                if self.__wiz.isPlatformVerifySubversionUpdates( name):
                    self.__checkbtnSubvVerify.set_active( True)
                else:
                    self.__checkbtnSubvVerify.set_active( False)

            self.__entryProjDir.set_sensitive( True)
            self.__entryProjDir.set_text( self.__wiz.getPlatformProjectDir( name))
            self.__textviewDescr.set_sensitive( True)
            self.__bufferDescr = self.__textviewDescr.get_buffer()
            self.__bufferDescr.set_text( self.__wiz.getPlatformDescription( name))
            self.__entryBuildDir.set_sensitive( True)
            self.__entryBuildDir.set_text( self.__wiz.getPlatformBuildDir( name))
            self.__entryCMakeListsDir.set_sensitive( True)
            self.__entryCMakeListsDir.set_text( self.__wiz.getPlatformCmakeListsDir( name))
            self.__isInitialShowVariables = False
        
        except BuildWizException, e:
            print 'ERROR: ', e 
        return

    def addVar( self, var, isInitialLoad = False):
        if not isInitialLoad:
            try:
                self.__wiz.addPlatformVariable( self.__comboPlatf.child.get_text(), var)
                if not self.__platfVars.has_key( var.getName()):
                    self.__platfVars[ var.getName()] = var

                self.__btnApply.set_sensitive( True)
            except BuildWizException, e:
                dlg = gtk.MessageDialog( None, 0, gtk.MESSAGE_ERROR
                                        , gtk.BUTTONS_OK, e.getStrError())
                dlg.run()
                dlg.destroy()
                return
        self.treeStore.append( None, (var.getName(), var.getType(), var.getValue()))

    def __showValues( self, values):
        self.__platfVars.clear()
        for varItem in values:
            self.__platfVars[ varItem.getName()] = varItem
            self.addVar( varItem, True) 

    def onBtnPenSettings( self, widget):
        dlg = DlgDeployPen( self.__wiz, self.__comboPlatf.child.get_text())
        response = dlg.run()
        if response == gtk.RESPONSE_OK:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setDeployPenValues( self.__comboPlatf.child.get_text(), dlg.getDeployValues())

    def onBtnLocalSettings( self, widget):
        return
    def onBtnRemoteSettings( self, widget):
        return
    def onBtnBoardSettings( self, widget):
        return

    def __onColumnChanged( self, treemodel, path, iter):
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setConfigVar( self.__platfChangedConfigs
                                         , treemodel[ path][ 0]
                                         , treemodel[ path][ 1]
                                         , treemodel[ path][ 2])
        else:
            self.__platfChangedConfigs = ""

    def __onBtnApply( self, widget):
        if len( self.__platfChangedConfigs) > 0: 
            self.__wiz.saveConfiguration( self.__platfChangedConfigs)
            self.__platfChangedConfigs = ""
        self.__btnApply.set_sensitive( False)

    def __onBtnOk( self, widget):
        if self.__shouldSaveConfigs():
            self.__onBtnApply( None)
        self.destroy( widget)
                
    def __onBtnCancel( self, widget):
        self.destroy( widget)

    def destroy( self, widget):
        self.__mainWin.enableConfigButton()
        self.win.destroy()

    def __onAddVar( self, widget):
        gladeFile = self.__wiz.getPreferences().getGUIFile( "addvarwindow")
        win = AddVariableWin( ''
                            , gladeFile
                            , self.__wiz.getCMakeKnownVariables()
                            , self)
        win.show()

    def __onDelVar( self, widget):
        selection = self.win.treeview.get_selection()
        model, modelIt, = selection.get_selected()
        if modelIt:
            path = model.get_path( modelIt)
            msg = "Are you really sure you want do delete variable:\n\n" \
                + model[ path][ 0] + ":" + model[ path][ 1] + "=" + model[ path][ 2] + " ?"
            question = gtk.MessageDialog( None, 0, gtk.MESSAGE_WARNING
                                        , gtk.BUTTONS_YES_NO, msg)
            response = question.run()
            question.destroy()

            if response == gtk.RESPONSE_YES:
                self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
                self.__wiz.delPlatformVariable( self.__platfChangedConfigs, model[ path][ 0])
                self.__btnApply.set_sensitive( True)
                if self.__platfVars.has_key( model[ path][ 0]):
                    del( self.__platfVars[ model[ path][ 0]])
                model.remove( modelIt) 
        else:
            info = gtk.MessageDialog( None, 0, gtk.MESSAGE_INFO
                                    , gtk.BUTTONS_OK, "Please, select an item to delete!")
            info.run()
            info.destroy()

    def __setScriptAreaSensibility( self, entry, btnEdit, onOff):
        entry.set_sensitive( onOff)
        btnEdit.set_sensitive( onOff)

    def __onCheckRunScriptBefore( self, chkbutton):
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setRunScriptBefore( self.__platfChangedConfigs
                                               , chkbutton.get_active())

        self.__setScriptAreaSensibility( self.__entryScriptBefore
                                       , self.__btnEditScriptBefore
                                       , chkbutton.get_active())
        

    def __onCheckRunScriptAfter( self, chkbutton):
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setRunScriptAfter( self.__platfChangedConfigs
                                              , chkbutton.get_active())

        self.__setScriptAreaSensibility( self.__entryScriptAfter
                                       , self.__btnEditScriptAfter
                                       , chkbutton.get_active())

    def __onEditScriptBefore( self, button):
        if len( self.__entryScriptBefore.get_text()) == 0:
            filename = self.__comboPlatf.child.get_text() + "-before.script"
            dlg = DlgFileSelection( "Create or choose a script to run before build process", filename)
            dlg.show()
            self.__entryScriptBefore.set_text( dlg.getFileName())

        if len( self.__entryScriptBefore.get_text()) > 0:
            try:
                scriptwin = ScriptWindow( self.__scriptWinFile
                                        , self.__wiz
                                        , self.__entryScriptBefore.get_text())
                scriptwin.show()

            except BuildWizException, e:
                dlgMsg = gtk.MessageDialog( None, 0, gtk.MESSAGE_ERROR,
                                          gtk.BUTTONS_OK, e.getStrError())
                dlgMsg.run()
                dlgMsg.destroy()


    def __onEditScriptAfter( self, button):
        #self.__btnApply.set_sensitive( True) 
        #self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
        return

    def __onCheckRunMakeInstall( self, chkbutton):
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setRunMakeInstall( self.__platfChangedConfigs
                                              , chkbutton.get_active())

    def __onSetNumMakeJobs( self, spin):
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            numJobs = spin.get_value_as_int()
            self.__wiz.setNumMakeJobs( self.__platfChangedConfigs, numJobs)

    def __onEntryScriptBeforeChanged( self, entry):
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setScriptBefore( self.__platfChangedConfigs, entry.get_text())
            
    def __onDescriptionChanged( self, entry):
        buf = entry.get_buffer()
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setDescriptionDir( buf.get_text())

    def __onProjDirChanged( self, entry):
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setPlatformProjectDir( self.__platfChangedConfigs,
                    entry.get_text())

    def __onBtnProjDir( self, btn):
        fs = DlgDirectorySelection( "Choose project diretory")
        selectdir = fs.getDirSelected()
        if len( selectdir) > 0:
            self.__entryProjDir.set_text( selectdir)

    def __onBuildDirChanged( self, entry):
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setPlatformBuildDir( self.__platfChangedConfigs, 
                    self.__entryBuildDir.get_text())

    def __onBtnBuildDir( self, btn):
        fs = DlgDirectorySelection( "Choose build diretory")
        selecteddir = fs.getDirSelected()
        if len( selecteddir) > 0:
            self.__entryBuildDir.set_text( selecteddir)

    def __onCMakeListsDirChanged( self, entry):
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setPlatformCmakeListsDir( self.__platfChangedConfigs, 
                    self.__entryCMakeListsDir.get_text())

    def __onBtnCMakeListsDir( self, btn):
        fs = DlgDirectorySelection( "Choose CMakeLists.txt diretory")
        selecteddir = fs.getDirSelected()
        if len( selecteddir) > 0:
            self.__entryCMakeListsDir.set_text( selecteddir)

    def __onCheckVerifySubversion( self, chkbtn):
        if not self.__isInitialShowVariables:
            self.__btnApply.set_sensitive( True) 
            self.__platfChangedConfigs = self.__comboPlatf.child.get_text()
            self.__wiz.setPlatformVerifySubvUpdates( self.__platfChangedConfigs,
                    chkbtn.get_active())
            self.__wiz.setPlatformSubversionURL( self.__platfChangedConfigs, 
                    self.__entrySubvURL.get_text())
            self.__wiz.setPlatformSubversionRevision( self.__platfChangedConfigs,
                    self.__entrySubvRevisionNumb.get_text())

    def __onImportClicked( self, btn):
        try:
            newVars = {}
            dlg = DlgImportVariables( self.__wiz, self.__comboPlatf.child.get_text()
                                    , self.__platfVars, newVars)
            response = dlg.run()
            if response == gtk.RESPONSE_OK: 
                for var in newVars.values():
                    self.addVar( var)

        except BuildWizException, e:
            dlgmsg = gtk.MessageDialog( None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
                    e.getStrError())
            dlgmsg.run()
            dlgmsg.destroy()

